package cqie.personal.frame.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cqie.personal.frame.bo.AddModifyCharacterBO;
import cqie.personal.frame.bo.GetCharacterBO;
import cqie.personal.frame.entity.CharacterInfo;
import cqie.personal.frame.entity.CharacterMenu;
import cqie.personal.frame.entity.MenuInfo;
import cqie.personal.frame.exception.DataBaseUpdateException;
import cqie.personal.frame.exception.ValidationFailException;
import cqie.personal.frame.mapper.CharacterInfoMapper;
import cqie.personal.frame.mapper.CharacterMenuMapper;
import cqie.personal.frame.mapper.CharacterViewMapper;
import cqie.personal.frame.mapper.MenuInfoMapper;
import cqie.personal.frame.service.CharacterInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cqie.personal.frame.vo.CharacterView;
import cqie.personal.frame.vo.PageVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Yeeeeee
 * @since 2021-09-08
 */
@Service
public class CharacterServiceImpl extends ServiceImpl<CharacterInfoMapper, CharacterInfo> implements CharacterInfoService {

    @Resource
    CharacterInfoMapper characterInfoMapper;
    @Resource
    MenuInfoMapper menuInfoMapper;
    @Resource
    CharacterMenuMapper characterMenuMapper;
    @Resource
    CharacterViewMapper characterViewMapper;

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    public synchronized boolean addCharacter(AddModifyCharacterBO addModifyCharacterBO) throws ValidationFailException, DataBaseUpdateException {
        if(addModifyCharacterBO == null){
            throw new ValidationFailException("∑(っ°Д°;)っ服务器被玩坏了，但肯定不是服务器的错");
        }
        CharacterInfo characterInfo = new CharacterInfo();
        if(addModifyCharacterBO.getCharacterName()!=null){
            QueryWrapper<CharacterInfo> queryWrapper;
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("character_name",addModifyCharacterBO.getCharacterName());
            if(characterInfoMapper.selectCount(queryWrapper)>0){
                throw new ValidationFailException("角色名被使用了,换一个吧");
            }
        }else {
            throw new ValidationFailException("角色不能命名为空哦");
        }
        if(addModifyCharacterBO.getMenuId()!=null&&addModifyCharacterBO.getMenuId().size()>0){
            QueryWrapper<MenuInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("id", addModifyCharacterBO.getMenuId());
            if(menuInfoMapper.selectCount(queryWrapper)!=addModifyCharacterBO.getMenuId().size()){
                throw new ValidationFailException("选择的部分菜单节点不可用啦");
            }
        }
        if(addModifyCharacterBO.getCharacterInfo()!=null) {
            characterInfo.setCharacterInfo(addModifyCharacterBO.getCharacterInfo());
        }
        QueryWrapper<CharacterInfo> idQueryWrapper = new QueryWrapper<>();
        idQueryWrapper.orderByDesc("id");
        idQueryWrapper.last(" LIMIT 1 ");
        int id ;
        try {
            id = characterInfoMapper.selectOne(idQueryWrapper).getId() + 1;
        }catch (Exception e){
            return false;
        }
        characterInfo.setId(id);
        characterInfo.setCharacterName(addModifyCharacterBO.getCharacterName());
        characterInfo.setCharacterAbandon(false);
        characterInfo.setLastUpgradePerson(addModifyCharacterBO.getUid());
        characterInfo.setCreatePerson(addModifyCharacterBO.getUid());
        Date date = new Date();
        characterInfo.setCreateTime(date);
        characterInfo.setLastUpgradeTime(date);
        if(characterInfoMapper.insert(characterInfo)!=1){
            throw new DataBaseUpdateException("w(ﾟДﾟ)w -啊 ， 数据库更新失败了，稍后重试一下吧");
        }
        for(int i : addModifyCharacterBO.getMenuId()){
            CharacterMenu characterMenu = new CharacterMenu();
            characterMenu.setCharacterId(id);
            characterMenu.setMenuId(i);
            if(characterMenuMapper.insert(characterMenu)!=1){
               throw new DataBaseUpdateException("w(ﾟДﾟ)w -啊 ， 数据库更新失败了，稍后重试一下吧");
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    public synchronized boolean modifyCharacter(AddModifyCharacterBO addModifyCharacterBO) throws ValidationFailException, DataBaseUpdateException {
        if(addModifyCharacterBO == null){
            throw new ValidationFailException("∑(っ°Д°;)っ服务器被玩坏了，但肯定不是服务器的错");
        }
        if(addModifyCharacterBO.getId()==null){
            throw new ValidationFailException("服务器君抽风了，稍后刷新重试一下吧");
        }
        QueryWrapper<CharacterInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",addModifyCharacterBO.getId());
        CharacterInfo characterInfo = characterInfoMapper.selectOne(queryWrapper);
        if(characterInfo ==null){
            throw new ValidationFailException("数据库里找不到这条数据o(╥﹏╥)o，换一个试试吧");
        }
        if(addModifyCharacterBO.getCharacterInfo()!=null){
            characterInfo.setCharacterInfo(addModifyCharacterBO.getCharacterInfo());
        }
        if(addModifyCharacterBO.getCharacterName()!=null){
            queryWrapper = new QueryWrapper<>();
            queryWrapper.ne("id",characterInfo.getId())
                    .eq("character_name",addModifyCharacterBO.getCharacterName());
            if(characterInfoMapper.selectCount(queryWrapper)>0){
                DecimalFormat g1=new DecimalFormat("0000");
                String startZeroStr = g1.format(characterInfo.getId());
                characterInfo.setCharacterName(addModifyCharacterBO.getCharacterName()+"#"+startZeroStr);
            }
        }else {
            throw new ValidationFailException("角色不能命名为空哦");
        }
        UpdateWrapper<CharacterInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",characterInfo.getId());
        if(characterInfoMapper.update(characterInfo,updateWrapper)!=1){
            throw new DataBaseUpdateException("w(ﾟДﾟ)w -啊 ， 数据库更新失败了，稍后重试一下吧");
        }
        QueryWrapper<CharacterView> characterViewQueryWrapper = new QueryWrapper<>();
        characterViewQueryWrapper.eq("id",characterInfo.getId());
        CharacterView characterView = characterViewMapper.selectOne(characterViewQueryWrapper);

        int menuId;
        if(characterView.getMenuId()!=null){
            menuId = characterView.getMenuId().split(",").length;
            QueryWrapper<CharacterMenu> delWrapper = new QueryWrapper<>();
            delWrapper.eq("character_id",characterInfo.getId());
            if(menuId!=characterMenuMapper.delete(delWrapper)){
                throw new DataBaseUpdateException("w(ﾟДﾟ)w -啊 ， 数据库更新失败了，稍后重试一下吧");
            }
        }
        for(int i : addModifyCharacterBO.getMenuId()){
            CharacterMenu characterMenu = new CharacterMenu();
            characterMenu.setCharacterId(characterInfo.getId());
            characterMenu.setMenuId(i);
            if(characterMenuMapper.insert(characterMenu)!=1){
                throw new DataBaseUpdateException("w(ﾟДﾟ)w -啊 ， 数据库更新失败了，稍后重试一下吧");
            }
        }
        return true;
    }

    @Override
    public PageVO<List<CharacterView>> getCharacter(GetCharacterBO character) throws ValidationFailException {
        if(character == null){
            throw new ValidationFailException("∑(っ°Д°;)っ服务器被玩坏了，但肯定不是服务器的错");
        }
        QueryWrapper<CharacterView> queryWrapper = new QueryWrapper<>();
        if(character.getCharacterAbandon()!=null){
            queryWrapper.eq("character_abandon",character.getCharacterAbandon());
        }
        if(character.getId()!=null){
            queryWrapper.eq("id",character.getId());
        }
        if(character.getCharacterName()!=null){
            queryWrapper.like("character_name",character.getCharacterName());
        }
        if(character.getCreatePerson()!=null){
            queryWrapper.eq("create_person",character.getCreatePerson());
        }
        if(character.getUid()!=null){
            queryWrapper.in("uid",character.getUid());
        }
        int totalCount = characterViewMapper.selectCount(queryWrapper);
        queryWrapper.last(" LIMIT "+character.getPageOff()+" , " + character.getPageMax());
        List<CharacterView> dataList = characterViewMapper.selectList(queryWrapper);
        List<CharacterView> result;
        PageVO<List<CharacterView>> pageResult = new PageVO<>();
        if(character.getMenuId()!=null&&character.getMenuId().size()>0){
            List<CharacterView> resultList = new ArrayList<>();
            for(CharacterView data : dataList){
                if(data.getMenuId()==null){
                    continue;
                }
                List<String> id = Arrays.asList(data.getMenuId().split(","));
                boolean t =true;
                for(String item : character.getMenuId()) {
                    if(id.contains(item)){
                        continue;
                    }
                    t=false;
                    break;
                }
                if(t){
                    resultList.add(data);
                }
            }
            if(resultList.size()<character.getPageMax()) {
                result = resultList.subList(0, resultList.size());
            }else {
                result = resultList.subList(0, character.getPageMax());
            }
            totalCount = resultList.size();
        }else{
            if(dataList.size()<character.getPageMax()){
                result = dataList.subList(0, dataList.size());
            }else {
                result = dataList.subList(0, character.getPageMax());
            }
        }
        pageResult.setData(result);
        pageResult.setPageNo(character.getPageNo());
        pageResult.setPageSize(character.getPageMax());
        pageResult.setRecordCount(pageResult.getData().size());
        pageResult.setTotalCount(totalCount);
        pageResult.setTotalPage(pageResult.getTotalCount() % pageResult.getPageSize() == 0 ?
                pageResult.getTotalCount() / pageResult.getPageSize() :
                pageResult.getTotalCount() / pageResult.getPageSize() + 1);
        return pageResult;
    }
}
